using System;
using System.Collections.Generic;
using System.Text;
using SpriteCraft;

namespace SpaceGame
{
  public abstract class Weapon : ICommand, IOnUpdate, IOnCollide
  {
    protected EngineClass m_Engine;
    protected ISpritesList m_Sprites;
    protected const long SHOT_SPEED = 200;
    protected long fire_last_frame;
    protected int m_CollideGroup;

    public Weapon(EngineClass engine, int collidegroup)
    {
      m_CollideGroup = collidegroup;

      m_Engine = engine;

      m_Sprites = m_Engine.NewSpritesList();

      m_Engine.executor.Schedule(this);
    }

    public virtual void Fire(Ship ship, FireDirection direction)
    {
    }

    public virtual void Make(float x, float y, float angle)
    {
    }

    #region Interfaces

    public virtual int Execute(IQue que)
    {
      throw new Exception("The method or operation is not implemented.");
    }

    public virtual void OnCollide(ISprite self, ISprite Hit)
    {
      throw new Exception("The method or operation is not implemented.");
    }

    public void OnUpdate(ISprite sprite, int tickdelta)
    {
    }

    #endregion

    public void DoStuff(Ship ship, int tickdelta)
    {
      FireDirection direction = FireDirection.none;

      if (m_Engine.IsKeyPressed(tagKeyVal.Key_W))
      { direction = FireDirection.up; }
      else if (m_Engine.IsKeyPressed(tagKeyVal.Key_D))
      { direction = FireDirection.right; }
      else if (m_Engine.IsKeyPressed(tagKeyVal.Key_S))
      { direction = FireDirection.down; }
      else if (m_Engine.IsKeyPressed(tagKeyVal.Key_A))
      { direction = FireDirection.left; }

      if (direction != FireDirection.none)
      {
        if (fire_last_frame + 100 < m_Engine.frameTick)
        {
          fire_last_frame = m_Engine.frameTick;
          Fire(ship, direction);
        }
      }
    }
  }

  public class LaserWeapon : Weapon
  {
    public LaserWeapon(EngineClass engine, int collidegroup)
      : base(engine, collidegroup)
    {
    }

    public override void Fire(Ship ship, FireDirection direction)
    {
      base.Fire(ship, direction);

      float x = ship.X;
      float y = ship.Y;
      if (direction == FireDirection.up)
      {
        y -= 5;
        x -= 1;
        Make(x, y, 0);
      }
      else if (direction == FireDirection.right)
      {
        x += 5;
        y -= 1;
        Make(x, y, (float)(2 * Math.PI) / 4 + (float)(2 * Math.PI) / 2);
      }
      else if (direction == FireDirection.down)
      {
        y += 5;
        x += 1;
        Make(x, y, (float)(2 * Math.PI) / 2);
      }
      else if (direction == FireDirection.left)
      {
        x -= 5;
        y += 1;
        Make(x, y, (float)(2 * Math.PI) / 4);
      }
      //m_Engine.PlaySound("player_fire_sound", 1, 
    }

    public override void Make(float x, float y, float angle)
    {
      base.Make(x, y, angle);

      ISprite shot;
      shot = m_Engine.NewSprite_("weapon_plasma", 1);
      shot.subimpl = this;
      shot.collide = m_CollideGroup;
      shot.x = x;
      shot.y = y;
      shot.angle = angle;
      shot.xScale = 50;
      m_Sprites.Add(shot);
    }

    public override int Execute(IQue que)
    {
      double delta;

      ISprite shot;
      delta = (double)que.delta / 1000;

      m_Sprites.Reset();

      while (m_Sprites.Next())
      {
        shot = m_Sprites.Get();
        if (shot.alive)
        {
          shot.y = (float)(shot.y - ((delta * SHOT_SPEED) * Math.Sin(shot.angle + 3.14 / 2)));
          shot.x = (float)(shot.x - ((delta * SHOT_SPEED) * -Math.Cos(shot.angle + 3.14 / 2)));

          if (shot.outOfScreen)
          {
            m_Sprites.Remove();
            shot.Dispose();
          }
        }
        else
        {
          m_Sprites.Remove();
        }
      }

      return (int)tagQueAny.CommandStateRepeat;
    }

    public override void OnCollide(ISprite self, ISprite Hit)
    {
      self.Dispose();
    }
  }

  public class DoubleLaserWeapon : Weapon
  {
    private bool m_Tuggler;

    public DoubleLaserWeapon(EngineClass engine, int collidegroup)
      : base(engine, collidegroup)
	  {

	  }

    public override void Fire(Ship ship, FireDirection direction)
    {
      base.Fire(ship, direction);

      float x = ship.X - 15;
      float y = ship.Y - 10;
      if (direction == FireDirection.up)
      {
        x = ship.X;
        if (m_Tuggler) { x = x + 32; }
        Make(x, y, 0);
      }
      else if (direction == FireDirection.right)
      {
        if (m_Tuggler) { y = y + 32; }
        Make(x, y, (float)(2 * Math.PI) / 4 + (float)(2 * Math.PI) / 2);
      }
      else if (direction == FireDirection.down)
      {
        if (m_Tuggler) { x = x + 32; }
        Make(x, y, (float)(2 * Math.PI) / 2);
      }
      else if (direction == FireDirection.left)
      {
        if (m_Tuggler) { y = y + 32; }
        Make(x, y, (float)(2*Math.PI)/4);
      }
      m_Tuggler = !m_Tuggler;
      //m_Engine.PlaySound("player_fire_sound", 1, 
    }

    public override void Make(float x, float y, float angle)
    {
 	    base.Make(x, y, angle);

      ISprite shot;
      shot = m_Engine.NewSprite_("weapon_plasma", 1);
      shot.subimpl = this;
      shot.collide = m_CollideGroup;
      shot.x = x;
      shot.y = y;
      shot.angle = angle;
      shot.xScale = 50;
      m_Sprites.Add(shot);
    }

    public override int Execute(IQue que)
    {
      double delta;

      ISprite shot;
      delta = (double)que.delta / 1000;

      m_Sprites.Reset();

      while(m_Sprites.Next())
      {
        shot = m_Sprites.Get();
        if (shot.alive)
        {
          shot.y = (float)(shot.y - ((delta * SHOT_SPEED) * Math.Sin(shot.angle + 3.14 / 2)));
          shot.x = (float)(shot.x - ((delta * SHOT_SPEED) * -Math.Cos(shot.angle + 3.14 / 2)));

          if (shot.outOfScreen)
          {
            m_Sprites.Remove();
            shot.Dispose();
          }
        }
        else
        {
          m_Sprites.Remove();
        }
      }

      return (int)tagQueAny.CommandStateRepeat;
    }

    public override void OnCollide(ISprite self, ISprite Hit)
    {
      int i = 0;
    }
  }

  public enum FireDirection
  {
    none, up,right,down,left
  }
}
